Skip to content

Add pgrust - #1163

Merged
alexey-milovidov merged 4 commits into
ClickHouse:mainfrom
malisper:add-pgrust
Aug 1, 2026
Merged

Add pgrust#1163
alexey-milovidov merged 4 commits into
ClickHouse:mainfrom
malisper:add-pgrust

Conversation

@malisper

Copy link
Copy Markdown

Adds pgrust, a from-scratch rewrite of
PostgreSQL in Rust (AGPL-3.0), wire- and SQL-compatible with PostgreSQL 18.3
(SELECT version() reports pgrust 0.2 (PostgreSQL 18.3 compatible)).

What this entry is (and is not)

  • It is not "PostgreSQL, but faster." For this benchmark the hits
    table uses pgrust's own columnar storage format (pgrcolumnar,
    declared as USING cbstore in create.sql), not the row-oriented heap
    the postgresql* entries use. The entry is tagged column-oriented
    accordingly. The engine executes the standard 43 queries through
    pgrust's parallel runtime over that columnar store.
  • pgrust is experimental and not production-ready. It cannot even
    bootstrap its own data directory yet: install uses C PostgreSQL 18's
    initdb (PGDG package, which also provides psql), then runs the
    pgrust server against that datadir.

Follow-up to #983

The previous attempt to add pgrust (#983, closed) used pgrust v0.1, whose
COPY path falsely rejected valid UTF-8 whenever a multi-byte character
straddled the 64 KiB buffer-refill boundary. The resulting ~690k-statement
split-load workaround could not finish inside the benchmark window and the
automated run produced no results. v0.2 fixes that defect; this entry loads
the dataset as a single COPY statement (measured load time: 197 s on
c8g.4xlarge) and has been verified end-to-end, unattended, on a fresh
c8g.4xlarge exactly as the automation would run it: clean Ubuntu 24.04
instance, clone, ./benchmark.sh, no manual steps.

Data ordering and the load-phase environment (please read)

Two things about the load phase deserve prominence rather than a code
comment:

  1. The load presorts the data into a clustered primary key. The load
    session sets PGRUST_COPY_PRESORT=counterid,eventdate,userid,eventtime, watchid, so the server sorts rows into that order while ingesting the
    single COPY. This is pgrust's mechanism for a clustered primary key —
    the same (CounterID, EventDate, UserID, EventTime, WatchID) key the
    ordered entries in this benchmark use (it is the ClickHouse entry's
    ORDER BY), expressed as a load-session environment variable because
    pgrust has no DDL syntax for it yet. The sort happens inside the timed
    load window and is paid for in load_time.
  2. The load phase is environment-tuned; the query phase is not. The
    full load-session environment is visible in load and is, in short:
    parallel COPY (DOP 16, stitch pool 8, fill prefetch), parallel parquet
    decode (4 GB budget), external-sort memory sizing (512 MB per run,
    15 GB in-memory run budget), lz4 for spilled sort runs, and a parallel
    ANALYZE sample pool. All of it affects only the measured load. Before
    the query sweep the server is restarted with no pgrust-specific
    environment: every scored query runs against stock server defaults,
    and the concurrent-QPS phase runs against that same stock server.

Setup notes, in the open

  • Binary: install downloads the official published v0.2 release
    binary for the machine's architecture (sha256-verified). These are
    generic-CPU builds for their architecture, with PGO trained on a corpus
    disjoint from the 43 queries. The results here are from that published
    binary — i.e. what anyone reproduces by running ./benchmark.sh.
  • Load format: the single as-published hits.parquet (format choice
    per the README's "select the most optimal dataset format at your
    discretion"; duckdb and others also load parquet). One COPY in one
    transaction (TRUNCATE + COPY ... FREEZE, then VACUUM ANALYZE).
    FORMAT 'parquet' / COERCE_EPOCH are pgrust COPY extensions that
    decode the parquet server-side and coerce its epoch-encoded time columns
    into the standard TIMESTAMP/DATE schema (the same conversion duckdb's
    entry expresses with epoch_ms()/make_date()).
  • Configuration: the machine-derived formula from postgresql/install,
    with two pgrust requirements (io_method=sync, max_stack_depth=60000
    • stack rlimits) and two open deviations, both general sizing rather than
      per-query tuning: work_mem = MemTotal/32 (pgrust executes analytical
      aggregation in work_mem-bounded hash state, so it is sized as a
      fraction of the machine like every other line of the formula, not fixed
      at an OLTP-era 64MB) and shared_buffers = MemTotal/8 (pgrust's columnar
      scans read through their own arenas and the OS page cache, so a 25%
      buffer pool is dead weight; the reclaimed headroom is what lets 10
      concurrent connections run the QPS phase safely). install also
      provisions the same 16 GB swapfile the benchmark automation's cloud-init
      gives every VM (no-op under the automation).
  • pgrust.condition_cache = on — enabled for parity with ClickHouse,
    and measured both ways.
    This is pgrust's equivalent of ClickHouse's
    query condition cache: a per-granule cache of filter-condition results
    with a 100 MB budget on both sides. ClickHouse ships this default-on
    since 25.4
    (use_query_condition_cache = true,
    src/Core/Settings.cpp:5925, flipped in SettingsChangesHistory.cpp),
    and the clickhouse entry here installs a current build — so the
    published ClickHouse rows already run with their condition cache
    enabled. pgrust's is off by default in v0.2; enabling it in this entry
    puts the two systems on the same footing rather than granting either an
    asymmetric advantage. Under ClickBench's caching rules this is a cache
    of intermediate filter results at the scan (front of the pipeline),
    not a query-result cache. For full transparency we measured both
    configurations on identical fresh instances: cache-off hot Σ43 is
    13.18 s versus 11.91 s cache-on (the delta concentrated in the
    LIKE-heavy URL queries — the same shape ClickHouse's cache targets), and
    the entry would score ~4% instead of ~16% ahead of the published
    ClickHouse c8g.4xlarge row on the combined metric. If the maintainers
    prefer the cache-off configuration for pgrust despite ClickHouse's
    default, we will happily switch the entry and results to that arm — both
    runs are complete.
  • Cold runs are true cold runs (server restart + page-cache drop per
    query; no lukewarm-cold-run tag). The concurrent-QPS test is kept
    (shared daemon, 10 connections).

Results

  • results/20260730/c8g.4xlarge.json — load_time 197.287 s, data_size
    17,563,161,388 B, all 43 queries, no nulls (hot Σ43 11.91 s, cold Σ43
    121.95 s); concurrent QPS 0.677 with error ratio 0.005. Row count
    verified: 99,997,497.

This entry submits c8g.4xlarge only. (pgrust currently has no JIT on
x86-64; an x86 row would not represent the engine and is deliberately not
included.)

Where this lands (against the published c8g.4xlarge rows, official
(t+10ms) geometric-mean scoring): cold runs are strong (well ahead of
the published ClickHouse row), hot runs slightly behind it, load time
197 s vs 287 s, data size 17.6 GB vs 15.3 GB. On the site's "Combined"
weighting this run reproduces to roughly the mid-teens percent ahead of
the published ClickHouse c8g.4xlarge row (and ~4% ahead with the condition
cache off, as disclosed above) — but per the ClickBench README we present
the numbers, not a scoreboard claim; they will move as neighboring entries
update.

The nonzero concurrent error ratio is real and disclosed: under the
10-connection window, a grouped string-aggregation shape occasionally
errors (aggregation sink shape violation, ~2 occurrences per 600 s
window; the statement fails cleanly, the server stays up). It is a known
v0.2 defect, tracked on the pgrust side.

🤖 Generated with Claude Code

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.


Michael Malis seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account.
You have signed the CLA already but the status is still pending? Let us recheck it.

@malisper
malisper temporarily deployed to benchmark-approval July 30, 2026 23:42 — with GitHub Actions Inactive
@github-actions

Copy link
Copy Markdown
Contributor

Results for pgrust are ready for: c6a.4xlarge.
The result files are committed as 5400145.
Removed manually added result files: pgrust/results/20260730/c8g.4xlarge.json.

Logs:

@malisper

Copy link
Copy Markdown
Author

Hey - pgrust was specifically designed for graviton. Our JIT compiler only targets the Graviton instruction set. Can you make sure to run it on the c8g.4xl?

@alexey-milovidov alexey-milovidov added the machine:all PR benchmark on every machine type label Aug 1, 2026
@alexey-milovidov alexey-milovidov self-assigned this Aug 1, 2026
@alexey-milovidov
alexey-milovidov deployed to benchmark-approval August 1, 2026 01:11 — with GitHub Actions Active
@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Results for pgrust are ready for: c6a.4xlarge, c6a.metal, c8g.4xlarge, c8g.metal-48xl.
The result files are committed as 1fe02bf.
The run of pgrust on t3a.small did not produce results.

Logs:

@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Results for pgrust are ready for: c6a.2xlarge, c6a.xlarge, c7a.metal-48xl.
The result files are committed as 4f21017.

Logs:

@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

The run of pgrust on c6a.large did not produce results.

Logs:

@alexey-milovidov
alexey-milovidov merged commit 325d7ab into ClickHouse:main Aug 1, 2026
1 of 2 checks passed
@alexey-milovidov

Copy link
Copy Markdown
Member

Very good results, thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

machine:all PR benchmark on every machine type

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants